home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Demo / pdist / cmdfw.py < prev    next >
Text File  |  1995-12-21  |  4KB  |  145 lines

  1. "Framework for command line interfaces like CVS.  See class CmdFrameWork."
  2.  
  3.  
  4. class CommandFrameWork:
  5.  
  6.     """Framework class for command line interfaces like CVS.
  7.  
  8.     The general command line structure is
  9.  
  10.         command [flags] subcommand [subflags] [argument] ...
  11.  
  12.     There's a class variable GlobalFlags which specifies the
  13.     global flags options.  Subcommands are defined by defining
  14.     methods named do_<subcommand>.  Flags for the subcommand are
  15.     defined by defining class or instance variables named
  16.     flags_<subcommand>.  If there's no command, method default()
  17.     is called.  The __doc__ strings for the do_ methods are used
  18.     for the usage message, printed after the general usage message
  19.     which is the class variable UsageMessage.  The class variable
  20.     PostUsageMessage is printed after all the do_ methods' __doc__
  21.     strings.  The method's return value can be a suggested exit
  22.     status.  [XXX Need to rewrite this to clarify it.]
  23.  
  24.     Common usage is to derive a class, instantiate it, and then call its
  25.     run() method; by default this takes its arguments from sys.argv[1:].
  26.     """
  27.  
  28.     UsageMessage = \
  29.       "usage: (name)s [flags] subcommand [subflags] [argument] ..."
  30.  
  31.     PostUsageMessage = None
  32.  
  33.     GlobalFlags = ''
  34.  
  35.     def __init__(self):
  36.         """Constructor, present for completeness."""
  37.         pass
  38.  
  39.     def run(self, args = None):
  40.         """Process flags, subcommand and options, then run it."""
  41.         import getopt, sys
  42.         if args is None: args = sys.argv[1:]
  43.         try:
  44.             opts, args = getopt.getopt(args, self.GlobalFlags)
  45.         except getopt.error, msg:
  46.             return self.usage(msg)
  47.         self.options(opts)
  48.         if not args:
  49.             self.ready()
  50.             return self.default()
  51.         else:
  52.             cmd = args[0]
  53.             mname = 'do_' + cmd
  54.             fname = 'flags_' + cmd
  55.             try:
  56.                 method = getattr(self, mname)
  57.             except AttributeError:
  58.                 return self.usage("command %s unknown" % `cmd`)
  59.             try:
  60.                 flags = getattr(self, fname)
  61.             except AttributeError:
  62.                 flags = ''
  63.             try:
  64.                 opts, args = getopt.getopt(args[1:], flags)
  65.             except getopt.error, msg:
  66.                 return self.usage(
  67.                     "subcommand %s: " % cmd + str(msg))
  68.             self.ready()
  69.             return method(opts, args)
  70.  
  71.     def options(self, opts):
  72.         """Process the options retrieved by getopt.
  73.         Override this if you have any options."""
  74.         if opts:
  75.             print "-"*40
  76.             print "Options:"
  77.             for o, a in opts:
  78.                 print 'option', o, 'value', `a`
  79.             print "-"*40
  80.  
  81.     def ready(self):
  82.         """Called just before calling the subcommand."""
  83.         pass
  84.  
  85.     def usage(self, msg = None):
  86.         """Print usage message.  Return suitable exit code (2)."""
  87.         if msg: print msg
  88.         print self.UsageMessage % {'name': self.__class__.__name__}
  89.         docstrings = {}
  90.         c = self.__class__
  91.         while 1:
  92.             for name in dir(c):
  93.                 if name[:3] == 'do_':
  94.                     if docstrings.has_key(name):
  95.                         continue
  96.                     try:
  97.                         doc = getattr(c, name).__doc__
  98.                     except:
  99.                         doc = None
  100.                     if doc:
  101.                         docstrings[name] = doc
  102.             if not c.__bases__:
  103.                 break
  104.             c = c.__bases__[0]
  105.         if docstrings:
  106.             print "where subcommand can be:"
  107.             names = docstrings.keys()
  108.             names.sort()
  109.             for name in names:
  110.                 print docstrings[name]
  111.         if self.PostUsageMessage:
  112.             print self.PostUsageMessage
  113.         return 2
  114.  
  115.     def default(self):
  116.         """Default method, called when no subcommand is given.
  117.         You should always override this."""
  118.         print "Nobody expects the Spanish Inquisition!"
  119.  
  120.  
  121. def test():
  122.     """Test script -- called when this module is run as a script."""
  123.     import sys
  124.     class Hello(CommandFrameWork):
  125.         def do_hello(self, opts, args):
  126.             "hello -- print 'hello world', needs no arguments"
  127.             print "Hello, world"
  128.     x = Hello()
  129.     tests = [
  130.         [],
  131.         ['hello'],
  132.         ['spam'],
  133.         ['-x'],
  134.         ['hello', '-x'],
  135.         None,
  136.         ]
  137.     for t in tests:
  138.         print '-'*10, t, '-'*10
  139.         sts = x.run(t)
  140.         print "Exit status:", `sts`
  141.  
  142.  
  143. if __name__ == '__main__':
  144.     test()
  145.